home *** CD-ROM | disk | FTP | other *** search
/ Programming Microsoft Visual Basic .NET / Programming Microsoft Visual Basic .NET (Microsoft Press)(X08-78517)(2002).bin / setup / vbnet / 06 interfaces and delegates / interfacesdemo / classes.vb < prev    next >
Encoding:
Text File  |  2002-03-16  |  17.2 KB  |  540 lines

  1. ' the Person class demonstrates the IComparable interface
  2.  
  3. Class Person
  4.     Implements IComparable
  5.  
  6.     ' Public fields
  7.     Public FirstName As String
  8.     Public LastName As String
  9.  
  10.     ' A simple constructor
  11.     Sub New(ByVal firstName As String, ByVal lastName As String)
  12.         Me.FirstName = firstName
  13.         Me.LastName = lastName
  14.     End Sub
  15.  
  16.     ' A property that returns the name in the format "Doe, Joe".
  17.     ReadOnly Property ReverseName() As String
  18.         Get
  19.             Return LastName & ", " & FirstName
  20.         End Get
  21.     End Property
  22.  
  23.     ' This procedure add sorting capabilities to the class.
  24.     Private Function CompareTo(ByVal obj As Object) As Integer _
  25.         Implements IComparable.CompareTo
  26.         ' Null objects always come before anything else.
  27.         If obj Is Nothing Then Return 1
  28.  
  29.         ' Cast to a specific Person object, to avoid late binding.
  30.         Dim other As Person = CType(obj, Person)
  31.         ' Use StrComp to simplify case-insensitive comparisons.
  32.         Return StrComp(ReverseName, other.ReverseName, CompareMethod.Text)
  33.     End Function
  34. End Class
  35.  
  36. ' this  version of the Person class demonstrates the IComparer interface
  37.  
  38. Class Person2
  39.     ' Public fields
  40.     Public FirstName As String
  41.     Public LastName As String
  42.  
  43.     ' A simple constructor
  44.     Sub New(ByVal firstName As String, ByVal lastName As String)
  45.         Me.FirstName = firstName
  46.         Me.LastName = lastName
  47.     End Sub
  48.  
  49.     ' A property that returns name in the format "Joe Doe".
  50.     ReadOnly Property CompleteName() As String
  51.         Get
  52.             Return FirstName & " " & LastName
  53.         End Get
  54.     End Property
  55.  
  56.     ' A property that returns name in the format "Doe, Joe".
  57.     ReadOnly Property ReverseName() As String
  58.         Get
  59.             Return LastName & ", " & FirstName
  60.         End Get
  61.     End Property
  62.  
  63.     ' Shared methods that return an auxiliary object.
  64.     Shared Function CompareByName() As IComparer
  65.         Return New ComparerByName()
  66.     End Function
  67.  
  68.     Shared Function CompareByReverseName() As IComparer
  69.         Return New ComparerByReverseName()
  70.     End Function
  71.  
  72.     ' First auxiliary class, to sort on CompleteName.  
  73.     Class ComparerByName
  74.         Implements IComparer
  75.  
  76.         Function Compare(ByVal o1 As Object, ByVal o2 As Object) _
  77.             As Integer Implements IComparer.Compare
  78.             ' Cast both objects to Person and do the comparison.
  79.             Dim p1 As Person2 = CType(o1, Person2)
  80.             Dim p2 As Person2 = CType(o2, Person2)
  81.             Return StrComp(p1.CompleteName, p2.CompleteName, _
  82.                 CompareMethod.Text)
  83.         End Function
  84.     End Class
  85.  
  86.     ' Second auxiliary class, to sort on ReverseName.
  87.     Class ComparerByReverseName
  88.         Implements IComparer
  89.  
  90.         Function Compare(ByVal o1 As Object, ByVal o2 As Object) _
  91.             As Integer Implements IComparer.Compare
  92.             ' Save code by casting to Person objects on the fly.
  93.             Return StrComp(CType(o1, Person2).ReverseName, _
  94.                 DirectCast(o2, Person2).ReverseName, CompareMethod.Text)
  95.         End Function
  96.     End Class
  97. End Class
  98.  
  99.  
  100. ' The IPluggableAddin and IHostEnvironment interfaces are implemented by the MyAddin class
  101.  
  102. Interface IPluggableAddin
  103.     Event Connected()
  104.  
  105.     ReadOnly Property Id() As Long
  106.  
  107.     Property State() As Boolean
  108.  
  109.     Function OnConnection(ByVal environment As String) As Boolean
  110.  
  111.     Sub OnDisconnection()
  112.  
  113.     Class PluginClass
  114.         ' an example of a class nested in an interface
  115.     End Class
  116.  
  117. End Interface
  118.  
  119. ' Another interface with just one property
  120. Interface IHostEnvironment
  121.     ReadOnly Property HashCode() As Long
  122. End Interface
  123.  
  124.  
  125. ' The MyAddin class implements the IPluggableAddin interface
  126.  
  127. Public Class MyAddin
  128.     ' You can have two distinct Implements statements, if you prefer so.
  129.     Implements IPluggableAddin, IHostEnvironment
  130.  
  131.     ' this class exposes the IDisposable interface
  132.     Implements IDisposable
  133.  
  134.     ' The following procedure implements two read-only properties
  135.     ' from distinct interfaces.
  136.     ReadOnly Property Id() As Long Implements IPluggableAddin.Id, IHostEnvironment.HashCode
  137.         Get
  138.             ' ...
  139.         End Get
  140.     End Property
  141.  
  142.  
  143.     Private Property State() As Boolean Implements IPluggableAddin.State
  144.         Get
  145.             ' ...
  146.         End Get
  147.         Set(ByVal Value As Boolean)
  148.             ' ...
  149.         End Set
  150.     End Property
  151.  
  152.     Protected Overridable Function OnConnection(ByVal Environment As String) _
  153.         As Boolean Implements IPluggableAddin.OnConnection
  154.         ' ...
  155.     End Function
  156.  
  157.     Private Sub OnDisconnection() Implements IPluggableAddin.OnDisconnection
  158.         ' ...
  159.     End Sub
  160.  
  161.     ' Dispose should always be defined as Overridable.
  162.     Overridable Sub Dispose() Implements IDisposable.Dispose
  163.         Console.WriteLine("Dispose method in MyAddin class")
  164.     End Sub
  165.  
  166.     Event Connected() Implements InterfacesDemo.IPluggableAddin.Connected
  167. End Class
  168.  
  169. ' the AnotherAddin class demonstrates that interfaces are inherited in derived classes
  170.  
  171. ' This class inherits all the interfaces defined in MyAddin class.
  172. Class AnotherAddin
  173.     Inherits MyAddin
  174.  
  175.     Protected Overrides Function OnConnection(ByVal Environment As String) As Boolean
  176.         ' ...
  177.     End Function
  178.  
  179.     Overrides Sub Dispose()
  180.         ' Clean-up code for the AnotherAddin class
  181.         ' ...(omitted)...
  182.         Console.WriteLine("Dispose method in AnotherAddin class")
  183.  
  184.         ' Complete the clean-up step by calling the base class's Dispose.
  185.         MyBase.Dispose()
  186.     End Sub
  187.  
  188. End Class
  189.  
  190. ' This is a simple interface with one function
  191.  
  192. Interface IGetObjectRef
  193.     Function GetObjectRef() As Object
  194. End Interface
  195.  
  196. ' This is a structure that implements an interface
  197. Structure MyStruct
  198.     Implements IGetObjectRef
  199.  
  200.     Dim x As Integer
  201.  
  202.     Public Function GetObjectRef() As Object Implements InterfacesDemo.IGetObjectRef.GetObjectRef
  203.         Return Me
  204.     End Function
  205. End Structure
  206.  
  207. ' A class for doing case-insensitive string comparisons the VB6 way
  208.  
  209. Class CaseInsensitiveComparerVB6
  210.     Implements IComparer
  211.  
  212.     Public Function Compare(ByVal o1 As Object, ByVal o2 As Object) As Integer Implements System.Collections.IComparer.Compare
  213.         Return StrComp(o1.ToString, o2.ToString, CompareMethod.Binary)
  214.     End Function
  215. End Class
  216.  
  217. ' The WordParser class and its nested class demonstrate the IEnumerable and IEnumerator interfaces
  218.  
  219. Class WordParser
  220.     ' This Implements statement means that this class supports For Each.
  221.     Implements IEnumerable
  222.  
  223.     ' The sentence being parsed
  224.     Public Source As String
  225.  
  226.     ' A simple constructor
  227.     Sub New(ByVal source As String)
  228.         Me.Source = source
  229.     End Sub
  230.  
  231.     ' This function is called when a For Each is encountered.
  232.     ' It must return an object that supports the IEnumerator interface.
  233.     Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
  234.         ' Return an instance of the nested class.
  235.         Return New WordParserEnumerator(Source)
  236.     End Function
  237.  
  238.     ' The nested class that supports IEnumerator.
  239.     Class WordParserEnumerator
  240.         ' This Implements statement ensures that this class can be used 
  241.         ' to enumerate items in a For Each.
  242.         Implements IEnumerator
  243.  
  244.         ' The sentence being parsed (passed in the constructor)
  245.         Dim Source As String
  246.         ' This index is used to visit all the characters in the sentence.
  247.         Dim CharIndex As Integer
  248.         ' The current word
  249.         Dim CurrentWord As String
  250.  
  251.         ' The outer class passes the Source string through this constructor.
  252.         Sub New(ByVal Source As String)
  253.             Me.Source = Source
  254.             ' Reset CharIndex.
  255.             Reset()
  256.         End Sub
  257.  
  258.         ' Reset the counter.
  259.         ' Note that Visual Basic.NET does *not* call this method when a For
  260.         ' Each loop starts, so you must call it in this class's constructor.
  261.         Private Sub Reset() Implements IEnumerator.Reset
  262.             CharIndex = 0
  263.         End Sub
  264.  
  265.         ' This property returns the current element.
  266.         Private ReadOnly Property Current() As Object _
  267.             Implements IEnumerator.Current
  268.             Get
  269.                 ' When VB.NET calls this property, the MoveNext method
  270.                 ' has already found the current word.
  271.                 Return CurrentWord
  272.             End Get
  273.         End Property
  274.  
  275. #Const USE_REGEX = True
  276.  
  277. #If Not USE_REGEX Then
  278.  
  279.         ' This function advances the pointer and returns True if a new word
  280.         ' has been found, False otherwise.
  281.         Private Function MoveNext() As Boolean Implements IEnumerator.MoveNext
  282.             ' Advance CharIndex if it is currently pointing to a separator.
  283.             Do While CharIndex < Len(Source) And _
  284.                 IsSeparator(Mid(Source, CharIndex + 1, 1))
  285.                 CharIndex += 1
  286.             Loop
  287.             ' Return False if there are no more characters.
  288.             If CharIndex >= Len(Source) Then Return False
  289.  
  290.             ' Remember current position of index.
  291.             Dim StartIndex As Integer = CharIndex
  292.  
  293.             ' Continue to loop until we find another separator.
  294.             Do While CharIndex < Len(Source) And _
  295.                 Not IsSeparator(Mid(Source, CharIndex + 1, 1))
  296.                 CharIndex += 1
  297.             Loop
  298.  
  299.             ' We found a new word.
  300.             CurrentWord = Mid(Source, StartIndex + 1, CharIndex - StartIndex)
  301.             ' Return True to signal success.
  302.             Return True
  303.         End Function
  304.  
  305.         ' Auxiliary function that determines whether a char is a separator.
  306.         Private Function IsSeparator(ByVal c As String) As Boolean
  307.             Return InStr(" ,.:;!?", c) > 0
  308.         End Function
  309. #Else
  310.         ' This regular expression searches for words
  311.         Dim re As New System.Text.RegularExpressions.Regex("\w+")
  312.  
  313.         ' This function advances the pointer and returns True if a new word
  314.         ' has been found, False otherwise.
  315.         Private Function MoveNext() As Boolean Implements IEnumerator.MoveNext
  316.             ' find the next word.
  317.             Dim ma As System.Text.RegularExpressions.Match
  318.             ma = re.Match(Source, CharIndex)
  319.  
  320.             ' Return False if there are no more characters.
  321.             If Not ma.Success Then Return False
  322.  
  323.             ' We found a new word.
  324.             CurrentWord = ma.Value
  325.  
  326.             ' Remember current position of index.
  327.             CharIndex = ma.Index + ma.Length
  328.  
  329.             ' Return True to signal success.
  330.             Return True
  331.         End Function
  332. #End If
  333.  
  334.     End Class
  335. End Class
  336.  
  337. ' an example of a cloneable class
  338.  
  339. Class Employee
  340.     Implements ICloneable
  341.  
  342.     Public FirstName As String
  343.     Public LastName As String
  344.     Public Boss As Employee
  345.  
  346.     Sub New(ByVal firstName As String, ByVal lastName As String)
  347.         Me.FirstName = firstName
  348.         Me.LastName = lastName
  349.     End Sub
  350.  
  351. #Const USE_MEMBERWISECLONE = True
  352.  
  353.     ' The only method of the ICloneable interface
  354.     Public Function Clone() As Object Implements ICloneable.Clone
  355.  
  356. #If USE_MEMBERWISECLONE Then
  357.         ' this is the easy way for doing shallow copying
  358.         Return Me.MemberwiseClone
  359.  
  360. #Else
  361.  
  362.         ' this block of code shows how to do "manual cloning".
  363.  
  364.         ' Create a new Employee with same property values.
  365.         Dim e As New Employee(FirstName, LastName)
  366.         ' Properties not accepted in the constructors must be copied manually.
  367.         e.Boss = Me.Boss
  368.         Return e
  369. #End If
  370.  
  371.     End Function
  372. End Class
  373.  
  374. ' an improved example of a clonable class
  375.  
  376. Class Employee2
  377.     Implements ICloneable
  378.  
  379.     Public FirstName As String
  380.     Public LastName As String
  381.     Public Boss As Employee2
  382.  
  383.     Sub New(ByVal firstName As String, ByVal lastName As String)
  384.         Me.FirstName = firstName
  385.         Me.LastName = lastName
  386.     End Sub
  387.  
  388.     ' The only method of the ICloneable interface
  389.     Public Function Clone() As Object Implements ICloneable.Clone
  390.         ' Start creating a shallow copy of this object.
  391.         ' (This copies all non-object properties in one operation)
  392.         Dim e As Employee2 = DirectCast(Me.MemberwiseClone, Employee2)
  393.  
  394.         ' manually copy the Boss property, reusing its Clone method.
  395.         If Not (e.Boss Is Nothing) Then
  396.             e.Boss = DirectCast(Me.Boss.Clone, Employee2)
  397.         End If
  398.         Return e
  399.     End Function
  400.  
  401. End Class
  402.  
  403. ' a cloneable class that uses a strongly typed Clone method.
  404.  
  405. Class Employee3
  406.     Implements ICloneable
  407.  
  408.     Public FirstName As String
  409.     Public LastName As String
  410.     Public Boss As Employee3
  411.  
  412.     Sub New(ByVal firstName As String, ByVal lastName As String)
  413.         Me.FirstName = firstName
  414.         Me.LastName = lastName
  415.     End Sub
  416.  
  417.     ' The only method of the ICloneable interface (private)
  418.     Private Function CloneMe() As Object Implements ICloneable.Clone
  419.         ' reuses the code in the strong-typed Clone method
  420.         Return Clone()
  421.     End Function
  422.  
  423.     Function Clone() As Employee3
  424.         ' Start creating a shallow copy of this object.
  425.         ' (This copies all non-object properties in one operation)
  426.         Clone = CType(Me.MemberwiseClone, Employee3)
  427.         ' manually copy the Boss property, reusing its Clone method.
  428.         If Not (Clone.Boss Is Nothing) Then
  429.             Clone.Boss = Me.Boss.Clone
  430.         End If
  431.     End Function
  432. End Class
  433.  
  434. ' this class shows how to support IEnumerable interface 
  435. ' it provides access to all files in a directory tree
  436.  
  437. Class FileTree
  438.     Implements IEnumerable
  439.  
  440.     ' the search path
  441.     Public ReadOnly DirPath As String
  442.  
  443.     ' the constructor
  444.     Sub New(ByVal DirPath As String)
  445.         Me.DirPath = DirPath
  446.     End Sub
  447.  
  448.     ' return an Enumerable object
  449.     Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
  450.         Return New FileTreeEnumerator(DirPath)
  451.     End Function
  452.  
  453.     ' the IEnumerator private object
  454.     Class FileTreeEnumerator
  455.         Implements IEnumerator
  456.  
  457.         Dim DirPath As String
  458.  
  459.         ' this contains the Enumerator object for the file list in current dir
  460.         Dim FileEnumerator As IEnumerator
  461.         ' these contain the stack of the Enumerator objects
  462.         ' for subdirectories of all pending directories
  463.         Dim DirEnumerators As New Stack()
  464.  
  465.         Sub New(ByVal DirPath As String)
  466.             ' save the directory path
  467.             Me.DirPath = DirPath
  468.             Reset()
  469.         End Sub
  470.  
  471.         Sub Reset() Implements IEnumerator.Reset
  472.             ' the DirectoryInfo object that represents the root object
  473.             Dim di As New System.IO.DirectoryInfo(DirPath)
  474.  
  475.             ' get the Enumerator object for the file list, and reset it
  476.             FileEnumerator = di.GetFiles.GetEnumerator
  477.             FileEnumerator.Reset()
  478.  
  479.             ' get the Enumerator object for subdir list and reset it
  480.             Dim dirEnum As IEnumerator = di.GetDirectories.GetEnumerator
  481.             dirEnum.Reset()
  482.             ' push it onto the stack
  483.             DirEnumerators.Push(dirEnum)
  484.         End Sub
  485.  
  486.         Function MoveNext() As Boolean Implements IEnumerator.MoveNext
  487.             ' Simply delegate to the File Enumerator object
  488.             If FileEnumerator.MoveNext Then
  489.                 ' it returned True, so we can exit
  490.                 Return True
  491.             End If
  492.  
  493.             ' if there are no files in the current directory, check whether
  494.             ' there is another subdir in the current directory
  495.  
  496.             ' first, get the current directory enumerator
  497.             Dim dirEnum As IEnumerator = CType(DirEnumerators.Peek, IEnumerator)
  498.  
  499.             ' check whether the current subdir enumerator has items
  500.             Do Until dirEnum.MoveNext
  501.                 ' there are no more subdirs at this level, so we must pop 
  502.                 ' another element of the stack
  503.                 DirEnumerators.Pop()
  504.  
  505.                 If DirEnumerators.Count = 0 Then
  506.                     ' Return False if there are no more subdirs to parse
  507.                     Return False
  508.                 End If
  509.  
  510.                 ' get the current enumerator
  511.                 dirEnum = CType(DirEnumerators.Peek, IEnumerator)
  512.             Loop
  513.  
  514.             ' we can create a DirectoryInfo
  515.             Dim di As System.IO.DirectoryInfo = CType(dirEnum.Current, System.IO.DirectoryInfo)
  516.  
  517.             ' store the file enumerator and reset it
  518.             FileEnumerator = di.GetFiles.GetEnumerator
  519.             FileEnumerator.Reset()
  520.  
  521.             ' get the Enumerator object for subdir list and reset it
  522.             dirEnum = di.GetDirectories.GetEnumerator
  523.             dirEnum.Reset()
  524.             ' push it onto the stack
  525.             DirEnumerators.Push(dirEnum)
  526.  
  527.             ' recursively call this routine, in order to process the file enumerator
  528.             Return Me.MoveNext
  529.  
  530.         End Function
  531.  
  532.         ' The current property simply delegates to FileEnumerator.Current
  533.         ReadOnly Property Current() As Object Implements IEnumerator.Current
  534.             Get
  535.                 Return FileEnumerator.Current
  536.             End Get
  537.         End Property
  538.  
  539.     End Class
  540. End Class